/*============================================================================
*  FILE: TurnLampModel.c
*=============================================================================
* Copyright  2025 Shanghai Hongqu Automobile Technology Co., LTD. 
* All rights reserved.
* Confidential - Restricted Shanghai Hongqu Automobile Technology Co., LTD. 
* Do not disclose.
*-----------------------------------------------------------------------------
*
*  DESCRIPTION:
*  	 Telltale TurnLamp Model Logic
*
*
*===========================================================================*/

#include "TurnLampModel.h"
#include "audio_service_api.h"

#include "ssas_api.h"

#define LOG_TAG "TT"
#include "log_api.h"

//TODO 需求描述


//TODO change AUDIO_0
#define TURN_LAMP_AUDIO_ID AUDIO_0
#define TURN_LAMP_BLINK_COUNT 30


LampWorkingData WorkingData;

static void TurnLampBlinkProcess(LampWorkingData* workData)
{
    if (workData->currentState != State_Off)
    {
        if(workData->blinkCountDown < TURN_LAMP_BLINK_COUNT) //0-29
        {
            if (WorkingData.currentState == State_LeftOn)
            {
                WorkingData.leftBlinkState = true;
                WorkingData.rightBlinkState = false;
            }
            else if (WorkingData.currentState == State_RightOn)
            {
                WorkingData.leftBlinkState = false;
                WorkingData.rightBlinkState = true;
            }
            else if (WorkingData.currentState == State_BothOn)
            {
                WorkingData.leftBlinkState = true;
                WorkingData.rightBlinkState = true;
            }
        }
        else if(workData->blinkCountDown >= TURN_LAMP_BLINK_COUNT && workData->blinkCountDown < TURN_LAMP_BLINK_COUNT*2)//30 59
        {
            
            WorkingData.leftBlinkState = false;    //处于闪烁的 灭灯阶段
            WorkingData.rightBlinkState = false;
        }
        else
        {
            LOG_E("blinkCountDown out of range : %d\n", workData->blinkCountDown);
        }

        if(workData->blinkCountDown >= (TURN_LAMP_BLINK_COUNT * 2 - 1))
        {
            workData->blinkCountDown = 0;
        }
        else
        {
            workData->blinkCountDown ++;
        }
    }
    else
    {
        WorkingData.leftBlinkState = false;
        WorkingData.rightBlinkState = false;
    }
}

static int TurnLampGetEvent(LampWorkingData* workData)
{
    uint16_t leftRawData;
    uint16_t rightRawData;

    //TODO timeout
    // if(get_message_state(CANIF_IC_Exterior_Lighting_HS))
    // {
    //     event = EV_Timeout;
    //     break;
    // }

    //TODO signal name
    if (Com_ReceiveSignal(COM_SID_LftTrnLmpAtv, &leftRawData) != E_OK)
    {
        LOG_W("erro receive signal COM_SID_LftTrnLmpAtv");
        return E_NOT_OK;
    }
    if (Com_ReceiveSignal(COM_SID_RtTrnLmpAtv, &rightRawData) != E_OK)
    {
        LOG_W("erro receive signal COM_SID_RtTrnLmpAtv");
        return E_NOT_OK;
    }

    if ((leftRawData == 0) && (rightRawData == 0))
    {
        workData->event = EV_BothOff;
    }
    else if ((leftRawData == 1) && (rightRawData == 1))
    {
        workData->event = EV_BothOn;
    }
    else if (leftRawData == 1)
    {
        workData->event = EV_LeftOn;
    }
    else if (rightRawData == 1)
    {
        workData->event = EV_RightOn;
    }
    else
    {
        LOG_W("receive wrong signal: %d, %d", leftRawData, rightRawData);
        workData->event = EV_Unknown;
        return E_NOT_OK;
    }

    return E_OK;
}

static void TurnLampStateTransition(LampWorkingData* workData)
{
    // state transition

    // LOG_D("start transition: %d, %d", workData->currentState, workData->event);

    switch(workData->currentState)
    {
        case State_Off:
            if (workData->event == EV_LeftOn)
            {
                audio_play_request(TURN_LAMP_AUDIO_ID);
                workData->currentState = State_LeftOn;
            }
            else if (workData->event == EV_RightOn)
                workData->currentState = State_RightOn;
            else if (workData->event == EV_BothOn)
                workData->currentState = State_BothOn;
            else
                break;
            
            break;
        case State_LeftOn:
            if (workData->event == EV_BothOff)
            {
                audio_stop(TURN_LAMP_AUDIO_ID);
                workData->currentState = State_Off;
            }
            else if (workData->event == EV_RightOn)
                workData->currentState = State_RightOn;
            else if (workData->event == EV_BothOn)
                workData->currentState = State_BothOn;
            break;
        case State_RightOn:
            if (workData->event == EV_BothOff)
            {
                audio_stop(TURN_LAMP_AUDIO_ID);
                workData->currentState = State_Off;
            }
            else if (workData->event == EV_LeftOn)
                workData->currentState = State_LeftOn;
            else if (workData->event == EV_BothOn)
                workData->currentState = State_BothOn;
            break;
        case State_BothOn:
            if (workData->event == EV_BothOff)
            {
                audio_stop(TURN_LAMP_AUDIO_ID);
                workData->currentState = State_Off;
            }
            break;

        default:
            //should not happen
            break;
    }

    // LOG_D("end transition: %d, %d", workData->currentState, workData->event);

}

static void init()
{
    WorkingData.event = EV_BothOff;
    WorkingData.leftBlinkState = Blink_Off;
    WorkingData.rightBlinkState = Blink_Off;
    WorkingData.currentState = State_Off;
    WorkingData.blinkCountDown = 0;
    WorkingData.hasleftTurnWidget = false;
    WorkingData.hasRightTurnWidget = false;
    //WorkingData.timestamp = //TODO current time or 0;
}

static void release()
{

}

static void run()
{
    // get event 
    TurnLampGetEvent(&WorkingData);
    // state transition
    TurnLampStateTransition(&WorkingData);
    // blinking logic
    TurnLampBlinkProcess(&WorkingData);
}

TurnLampModel g_turnLampModelInstance = {
    // ImeterModel
    {
        init,
        run,
        release,
        MIN_PERIOD, //TODO
    },
};

// ----------------------------------View------------------------------
void refresh_LeftTurnView(ItuElement* elememt)
{
    ituWidgetSetVisible(elememt->widget_, WorkingData.leftBlinkState);
}

void reporting_self_validity_LeftTurnView(ItuElement* elememt)
{
    WorkingData.hasleftTurnWidget = (elememt && elememt->isVaild_) ? true : false;
}

void refresh_RightTurnView(ItuElement* elememt)
{
    ituWidgetSetVisible(elememt->widget_, WorkingData.rightBlinkState);
}

void reporting_self_validity_RightTurnView(ItuElement* elememt)
{
    WorkingData.hasRightTurnWidget = (elememt && elememt->isVaild_) ? true : false;
}
